#include "tcpmodbdev.h"
#include "KgGlobalData.h"
#include "rtdb.h"
#include <math.h>
#include "tcpmodbdev.h"

#define RUN_LOG_MODBUS_PCS              190  //PCS modbus 报文
#define RUN_LOG_MESSAGE_PCS             200  //PCS操作报文
#define RUN_LOG_FAILED_PCS              210  //PCS操作失败报文
#define WAIT_DEV_TIME					1500 // added 2020-6-3 //3000
#define DEV_ADDR     1

void getSystemTime(char time_buf[50]);

void saveLogToBaDb(const QString& strContextCn, const QString& strContextEn);

quint16 getUint16(float fVal);
float getRealVal(quint16 uVal, float rate);

void PrintLog(char *str, char *pData, int length)
{
    //return;
    int i;
    printf("%s",str);
    for(i = 0; i < length; ++i)
        printf("%02x ",  *(pData+i));
    printf("\n");
}

CModbusFactory::CModbusFactory()
{

}

CModbusFactory::~CModbusFactory()
{

}

int CModbusFactory::addParam2Buffer(char* pData, quint32 uiParamVal)
{
    *pData = (char)(uiParamVal >> 24);

    ++pData;
    *pData = (char)(uiParamVal >> 16);

    ++pData;
    *pData = (char)(uiParamVal >> 8);

    ++pData;
    *pData = (char)(uiParamVal);

    return  0;
}

int CModbusFactory::addParam2Buffer(char* pData, quint16 uiParamVal)
{
    *pData = (char)(uiParamVal >> 8);

    ++pData;
    *pData = (char)(uiParamVal);

    return  0;
}

int CModbusFactory::addParam2Buffer(char* pData, float fParamVal)
{
    char aTemp[4];
    memcpy(aTemp, &fParamVal, 4);

    *pData = aTemp[3];
    ++pData;
    *pData = aTemp[2];
    ++pData;
    *pData = aTemp[1];
    ++pData;
    *pData = aTemp[0];

    return 0;
}

int CModbusFactory::addParam2Buffer(char* pData, uchar ucParamVal)
{
    *pData = (char)(ucParamVal);
}

int CModbusFactory::addParam2BufferSmall(char* pData, quint16 uiParamVal)
{
    *pData = (char)(uiParamVal);

    ++pData;
    *pData = (char)(uiParamVal >> 8);

    return  0;
}

int CModbusFactory::getParamFromBuffer(char* pData, qint16& uiParamVal)
{
    uiParamVal = (unsigned char)*pData;
    uiParamVal = uiParamVal * 256;

    ++pData;

    uiParamVal += (unsigned char)*pData;

    return 0;
}

int CModbusFactory::getParamFromBuffer(char* pData, quint16& uiParamVal)
{
    uiParamVal = (unsigned char)*pData;
    uiParamVal = uiParamVal * 256;

    ++pData;

    uiParamVal += (unsigned char)*pData;

    return 0;
}

int CModbusFactory::getParamFromBuffer(char* pData, quint32& uiParamVal)
{
    uiParamVal = (unsigned char)*pData;

    uiParamVal = uiParamVal * 256;
    ++pData;
    uiParamVal += (unsigned char)*pData;

    uiParamVal = uiParamVal * 256;
    ++pData;
    uiParamVal += (unsigned char)*pData;

    uiParamVal = uiParamVal * 256;
    ++pData;
    uiParamVal += (unsigned char)*pData;

    return 0;
}

int CModbusFactory::getParamFromBuffer(char* pData, float& fParamVal) 
{
    // 解析大端格式数据 //FF C0 00 00 = nan (schneider-meter)
    char aTemp[4];
    aTemp[3] = *pData;
    ++pData;
    aTemp[2] = *pData;
    ++pData;
    aTemp[1] = *pData;
    ++pData;
    aTemp[0] = *pData;

    // 无效数据处理
    if(0xFF == aTemp[3] && 0xC0 == aTemp[2]  && 0x00 == aTemp[1]  &&  0x00 == aTemp[0])
    {
        fParamVal = 0;
        return 0;
    }

    memcpy(&fParamVal, aTemp, 4);
    return 0;
}

int CModbusFactory::getParamFromBufferSmall(char* pData, float& fParamVal)
{
    // 解析小端格式数据	//00 00 C0 FF = nan
    char aTemp[4];
    aTemp[0] = *pData;
    ++pData;
    aTemp[1] = *pData;
    ++pData;
    aTemp[2] = *pData;
    ++pData;
    aTemp[3] = *pData;

    // 无效数据处理
    if(0xFF == aTemp[3] && 0xC0 == aTemp[2]  && 0x00 == aTemp[1]  &&  0x00 == aTemp[0])
    {
        fParamVal = 0;
        return 0;
    }

    memcpy(&fParamVal, aTemp, 4);
    return 0;
} 

int CModbusFactory::formDatagram(quint16 usEvent, uchar uaAddr, uchar uaFuncCode, quint16 usStartReg, quint16 usRegNum, char* pSendDataBuf)
{
    int iLenVal = 0;
    quint16 usTemp = 0;

    addParam2Buffer(pSendDataBuf, usEvent);
    iLenVal += 2;

    usTemp = 0;
    addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
    iLenVal += 2;        // 协议标识

    usTemp = 6;          // 长度
    addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
    iLenVal += 2;

    *(pSendDataBuf + iLenVal) = uaAddr;
    iLenVal += 1;

    *(pSendDataBuf + iLenVal) = uaFuncCode;
    iLenVal += 1;

    usTemp = usStartReg;
    addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
    iLenVal += 2;

    usTemp = usRegNum;
    addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
    iLenVal += 2;

    return iLenVal;
}

int CModbusFactory::formSetSinglegram(quint16 usEvent, uchar uaAddr, quint16 usRegAddr, quint16 usRegVal, char* pSendDataBuf)
{
    int iLenVal = 0;
    quint16 usTemp = 0;

    addParam2Buffer(pSendDataBuf, usEvent);
    iLenVal += 2;

    iLenVal += 2;        // 协议标识

    usTemp = 6;          // 长度
    addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
    iLenVal += 2;

    *(pSendDataBuf + iLenVal) = uaAddr;
    iLenVal += 1;

    *(pSendDataBuf + iLenVal) = 0x6;//uaFuncCode; 单项调节保持寄存器 06H
    iLenVal += 1;

    usTemp = usRegAddr;
    addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
    iLenVal += 2;

    usTemp = usRegVal;
    addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
    iLenVal += 2;

    return iLenVal;
}

int CModbusFactory::formSetMultgram(quint16 usEvent, uchar uaAddr, quint16 usRegAddr, quint16 regCount, quint16 *usRegValBuf, char* pSendDataBuf)
{
    int iLenVal = 0;
    quint16 usTemp = 0;

    addParam2Buffer(pSendDataBuf, usEvent);
    iLenVal += 2;

    iLenVal += 2;        // 协议标识

    usTemp = regCount*2+7;          // 长度
    addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
    iLenVal += 2;

    *(pSendDataBuf + iLenVal) = uaAddr;
    iLenVal += 1;

    *(pSendDataBuf + iLenVal) = 0x10;//uaFuncCode; 多项调节保持寄存器 10H
    iLenVal += 1;

    usTemp = usRegAddr;
    addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
    iLenVal += 2;

    usTemp = regCount;
    addParam2Buffer(pSendDataBuf + iLenVal, usTemp);
    iLenVal += 2;

    *(pSendDataBuf + iLenVal) = regCount*2;
    iLenVal += 1;

    for(int i = 0; i < regCount; ++i)
    {
        addParam2Buffer(pSendDataBuf + iLenVal, usRegValBuf[i]);
        iLenVal += 2;
    }

    return iLenVal;
}

int CModbusFactory::analySetSingleDatagram(quint16 usSdEvent, char* pRecDataBuf, int iLen, quint16 usRegAddr, quint16 usRegVal, char devAddr)
{
    // some varibales
    int iRetVal = 0;
    int iInedx = 0;
    quint16 usEvent = 0;
    quint16 usLen = 0;
    uchar uaModbusAddr = 0;
    uchar uaFuncCode = 0;
    uchar uaByteNum = 0;

    uchar uaTemp8 = 0;
    quint16 usTemp16 = 0;
    quint32 uiTemp32 = 0;
    float fTemp = 0;

    quint16 usRepRegAddr =0;
    quint16 usRepRegVal =0;

    // 校验报文是否正确
    iInedx = 0;

    getParamFromBuffer(pRecDataBuf, usEvent);
    iInedx += 2;

    iInedx += 2;  // 协议标识

    getParamFromBuffer(pRecDataBuf + iInedx, usLen);
    iInedx += 2;

    uaModbusAddr = (uchar)*(pRecDataBuf + iInedx);
    iInedx += 1;

    uaFuncCode = (uchar)*(pRecDataBuf + iInedx);
    iInedx += 1;

    if (devAddr != uaModbusAddr || iLen != usLen + 6 /*|| usLen != uaByteNum + 3*/) // 校验失败
    {
        return -2;
    }


    if(6!= uaFuncCode)//单项调节保持寄存器 06H
    {
        iRetVal = -3;
    }
    else if (usSdEvent != usEvent)//下设命令标识
    {
        iRetVal = -4;
    }
    else
    {
        getParamFromBuffer(pRecDataBuf + iInedx, usTemp16);
        iInedx += 2;
        usRepRegAddr= usTemp16;          //addr

        getParamFromBuffer(pRecDataBuf + iInedx, usTemp16);
        iInedx += 2;
        usRepRegVal= usTemp16;          //value

        if(usRepRegAddr==usRegAddr && usRepRegVal==usRegVal)
        {
            iRetVal = 0;
        }
        else
        {
            iRetVal = -5;
        }
    }
    return iRetVal;
}

int CModbusFactory::analySetMultDatagram(quint16 usSdEvent, char* pRecDataBuf, int iLen, quint16 usRegAddr, quint16 regCount)
{
    // some varibales
    int iRetVal = 0;
    int iInedx = 0;
    quint16 usEvent = 0;
    quint16 usLen = 0;
    uchar uaModbusAddr = 0;
    uchar uaFuncCode = 0;
    uchar uaByteNum = 0;

    uchar uaTemp8 = 0;
    quint16 usTemp16 = 0;
    quint32 uiTemp32 = 0;
    float fTemp = 0;

    quint16 usRepRegAddr =0;
    quint16 modifiedCount =0;

    // 校验报文是否正确
    iInedx = 0;

    getParamFromBuffer(pRecDataBuf, usEvent);
    iInedx += 2;

    iInedx += 2;  // 协议标识

    getParamFromBuffer(pRecDataBuf + iInedx, usLen);
    iInedx += 2;

    uaModbusAddr = (uchar)*(pRecDataBuf + iInedx);
    iInedx += 1;

    uaFuncCode = (uchar)*(pRecDataBuf + iInedx);
    iInedx += 1;

    if (DEV_ADDR != uaModbusAddr || iLen != usLen + 6 /*|| usLen != uaByteNum + 3*/) // 校验失败
    {
        return -2;
    }


    if(0x10!= uaFuncCode)//多项调节保持寄存器 10H
    {
        iRetVal = -3;
    }
    else if (usSdEvent != usEvent)//多项调节保持寄存器标识
    {
        iRetVal = -4;
    }
    else
    {
        getParamFromBuffer(pRecDataBuf + iInedx, usTemp16);
        iInedx += 2;
        usRepRegAddr= usTemp16;          //addr

        getParamFromBuffer(pRecDataBuf + iInedx, usTemp16);
        iInedx += 2;
        modifiedCount= usTemp16;          //register count

        if(usRepRegAddr==usRegAddr && regCount==modifiedCount)
        {
            iRetVal = 0;
        }
        else
        {
            iRetVal = -4;
        }
    }
    return iRetVal;
}

//added by zyx 2019-7-3 begin
int CModbusFactory::analyReplayDatagram(char* pDataBuf, int iLen, SMdobusTcpReply& reply, int readRegCount)
{
    if(0 == pDataBuf || iLen < 11)
    {
        return -1;
    }
    reply.usEvent = 0;
    reply.usProto = 0;
    reply.usLen = 0;
    reply.uaAddr = 0;
    reply.uaFuncCode = 0;
    reply.usDataLen = 0;

    // Read Data
    int iInedx = 0;

    getParamFromBuffer(pDataBuf, reply.usEvent);
    iInedx += 2;

    getParamFromBuffer(pDataBuf + iInedx, reply.usProto);
    iInedx += 2;

    getParamFromBuffer(pDataBuf + iInedx, reply.usLen);
    iInedx += 2;

    reply.uaAddr = (uchar)*(pDataBuf + iInedx);
    iInedx += 1;

    reply.uaFuncCode = (uchar)*(pDataBuf + iInedx);
    iInedx += 1;

    quint16 usRegAddr  = 0;
    quint16 usRegCount = 0;

    // 校验报文是否正确
    if (2== reply.uaSendFuncCode)
    {
        reply.usDataLen = (uchar)*(pDataBuf + iInedx);
        iInedx += 1;

        int dataLen = (readRegCount+1)/8;
        if (reply.usDataLen != dataLen)
        {
            printf("first %d != %d\n", reply.usDataLen, dataLen);
            return -1;
        }
    }
    else if (3 == reply.uaFuncCode || 4 == reply.uaFuncCode)
    {
        reply.usDataLen = (uchar)*(pDataBuf + iInedx);
        iInedx += 1;

        if (reply.usDataLen != readRegCount*2)
        {
            printf("sec %d != %d\n", reply.usDataLen, readRegCount*2);
            return -2;
        }
    }
    else if (6 == reply.uaFuncCode || 16 == reply.uaFuncCode)
    {
        getParamFromBuffer(pDataBuf + iInedx, usRegAddr);
        iInedx += 2;

        getParamFromBuffer(pDataBuf + iInedx, usRegCount);
        iInedx += 2;
    }
    else
        ;

    //if(3 != reply.uaFuncCode && 4 != reply.uaFuncCode)
    if (reply.uaFuncCode != reply.uaSendFuncCode)
    {
        printf("thd %d != %d\n", reply.uaFuncCode, reply.uaSendFuncCode);
        return -3;
    }

    if(6 == reply.uaFuncCode || 16 == reply.uaFuncCode)
    {
        if (reply.uaSendRegAddr != usRegAddr || readRegCount != usRegCount)
        {
            printf("fourth error send regAddr:%d, regCount%d, read regAddr:%d, regCount%d\n",
                   reply.uaSendRegAddr, readRegCount, usRegAddr, usRegCount);
            return -4;
        }
        else
        {
            printf("fourth right send regAddr:%d, regCount%d, read regAddr:%d, regCount%d\n",
                   reply.uaSendRegAddr, readRegCount, usRegAddr, usRegCount);
        }
    }

    return 0;
}

int CModbusFactory::getParamFromBuffer(char* pData, uchar& uiParamVal)
{
    uiParamVal = (unsigned char)*pData;
    return 0;
}

int CModbusFactory::getParamFromBuffer(char* pData, quint64& uiParamVal)
{
    quint32 big = 0;
    quint32 small = 0;
    getParamFromBuffer(pData,big);
    pData += 4;
    getParamFromBuffer(pData,small);
    uiParamVal = big*256*256*256*256 + small;
}

void get_current_time(int *year, int *month, int *day, int *hour, int *minu, int *sec)
{
#ifdef XNLINUX
    time_t timep;
    struct tm *p;
    time(&timep);
    p=localtime(&timep);
    *year = p->tm_year+1900;
    *month =p->tm_mon+1;
    *day = p->tm_mday;
    *hour =p->tm_hour;
    *minu = p->tm_min;
    *sec = p->tm_sec;
#endif
}

void getSystemTime(char time_buf[50])
{
    int year,month,day, hour, minu,sec;
    get_current_time(&year,&month,&day,&hour,&minu,&sec);
    sprintf(time_buf, "time:%04d-%02d-%02d %02d:%02d:%02d",year,month,day,hour,minu,sec);
}

int g_printRpCount = 0;
void TcpModbDev::SaveSendRecvLog( unsigned char *data, int dataLength, bool isSended)
{
    if(g_printRpCount < 30)
    {
        g_printRpCount += 1;
    }
    else
    {
        return;
    }

    UINT8 addr;
    char time_buf[50];
    char tmp[350];
    QString strLog;
    int i;

    if (dataLength >= 250)
        return;

    getSystemTime(time_buf);
    if (isSended)
        sprintf(tmp, "%s, TcpModbDev port:%d send data:", time_buf, m_usPort);//时间
    else
        sprintf(tmp, "%s, TcpModbDev port:%d recv data:", time_buf, m_usPort);//时间
    strLog = tmp;

    for(i = 0; i < dataLength; ++i)//;
    {
        sprintf(tmp, "%02X ", data[i]);//以16进制占两位格式输出
        strLog += tmp;
    }

    writeKgLogfile(strLog);
    return;
}

TcpModbDev::TcpModbDev(QObject *parent)
    : QThread(parent)
{
    m_pDataBuf = new char[SNED_BUFFER_LENGHT];
    m_pSendBuf = new char[SNED_BUFFER_LENGHT];

    m_pModbusFactory = new CModbusFactory;
    m_pTcpClient = 0;

    m_strIP =  "127.0.0.1";
    m_usPort = 502;
    m_bTcpConnected = false;

    m_uaFuncCode = 0;
    m_iErrNum = 0;

    m_saveRdCount = 0;

    m_connErrorLog = 99;


}

TcpModbDev::~TcpModbDev()
{
    if (m_pDataBuf)
    {
        delete []m_pDataBuf;
        m_pDataBuf = 0;
    }

    if (m_pSendBuf)
    {
        delete []m_pSendBuf;
        m_pSendBuf = 0;
    }

    if (m_pModbusFactory)
    {
        delete m_pModbusFactory;
        m_pSendBuf = 0;
    }
}

void TcpModbDev::setPara(QString strIp, int port)
{
    m_strIP = strIp;
    m_usPort = port;
}

void TcpModbDev::disconnected()
{
    m_bTcpConnected = false;
    printf("TcpModbDev::disconnected()\n");
}

void TcpModbDev::KgSleep(int timespan)
{
    msleep(timespan);
}

int TcpModbDev::sendRecvData(char* pataBuf, int regCount, int iRetVal)
{
    //this->msleep(600); // 不加延时，USR-668有时会读取数据失败，虽然串口设备已回复数据 added 2020-6-3
    this->msleep(100);
    int iIndexStep = 1000;
    SaveSendRecvLog((unsigned char *)pataBuf, iRetVal, true);

    if(iRetVal != m_pTcpClient->write(pataBuf, (qint64)iRetVal))
    {
        ++m_iErrNum;
        printf("Write data to dev FAILED.\n");
    }
    else
    {
        m_pTcpClient->flush();
        // receive data
        if (!m_pTcpClient->waitForReadyRead(WAIT_DEV_TIME)) // timeout
        {
            ++m_iErrNum;
            printf("Read data timeout.\n");
        }
        else
        {
            memset(m_pDataBuf, 0, SNED_BUFFER_LENGHT);
            iRetVal = m_pTcpClient->read(m_pDataBuf, SNED_BUFFER_LENGHT);
            m_iErrNum = 0; // 分析正确清空  此处要清0，否则读取失败就会累计，从而关闭连接 2020-4-16

            if (iRetVal > 0) // read OK
            {
                //printf("TcpModbDev step3,iRetVal:%d\n", iRetVal);
                SaveSendRecvLog((unsigned char *)m_pDataBuf, iRetVal, false);
                //printf("TcpModbDev step4\n");
                SMdobusTcpReply reply;
                reply.uaSendFuncCode = m_uaFuncCode;
                reply.uaSendRegAddr =  m_usRegAddr;
                if (0 == m_pModbusFactory->analyReplayDatagram(m_pDataBuf,iRetVal,reply,regCount))
                {
                    //printf("TcpModbDev step5\n");
                    return 0;
                }
                //printf("TcpModbDev step6\n");
            }
            else
            {
            }
        }
    }
    return -1;
}

int g_iEvent = 0;
void TcpModbDev::KgReadDevData(BrotherBaData &dev)
{
    int iLenVal = 0;
    int regCount = 0;
    int iInedx = 0;
    QString str;

    str = QString("read AC data (devAddr:%1)").arg(dev.devAddr);
    writeKgLogfile(str);

    regCount = 2; // 2个IO数据
    m_uaFuncCode = 3;
    m_usRegAddr = 40;
    if(++g_iEvent > 100)
        g_iEvent = 1;
    iLenVal =  m_pModbusFactory->formDatagram(g_iEvent, dev.devAddr, m_uaFuncCode, m_usRegAddr, regCount, m_pSendBuf);
    if (0 == sendRecvData(m_pSendBuf,regCount,iLenVal))
    {
        readDevData1(m_pDataBuf,0,dev);// 注意是m_pDataBuf, 而不是m_pSendBuf
        dev.failedCount = 0;
        writeKgLogfile(QString("||||||Read Dev data1 OK (devAddr:%1) xfState:%2, ohterState:%3.")
                           .arg(dev.devAddr).arg(dev.xfState).arg(dev.otherState));
    }
    else
    {
        if(dev.failedCount < 1000)
        {
            dev.failedCount += 1;
        }
        //writeKgLogfile(QString("Read Dev data1 failed (devAddr:%1) m_iErrNum:%2").arg(dev.devAddr).arg(m_iErrNum));
    }
}

int g_heartbeat = 1;
int g_testLogCount = 0;
int g_testLogSecCount = 0;
/*
usStackHoldTemp[35]	电池组总电压 V
usStackHoldTemp[36]	电池组总电流 A
usStackHoldTemp[37]	SOC	 0.1
usStackHoldTemp[38]	SOH	 0.1
usStackHoldTemp[39]	电池组最大允许充电电流	A
usStackHoldTemp[40]	电池组最大允许放电电流	A
usStackHoldTemp[41]	电池组最大允许充电功率	kW
usStackHoldTemp[42]	电池组最大允许放电功率	kW
usStackHoldTemp[43]	无	BMS总状态	0x1111禁充 0x2222禁放 0x5555告警 0xAAAA故障 0xBBBB正常
usStackHoldTemp[44]	无	主接触器状态	1-闭合 2-断开
usStackHoldTemp[45]	无	轻度告警字	Bit0:单体SOC过高 ...Bit15:放电过流
usStackHoldTemp[46]	无	中度告警字	Bit0:单体SOC过高 ...Bit15:放电过流
usStackHoldTemp[47]	无	严重告警字	Bit0:单体SOC过高 ...Bit15:放电过流
usStackHoldTemp[48]	无	BMS状态字	"Bit0:1-BMS与EMS通信故障 0-BMS与EMS通信正常
                                  Bit2-Bi3:0-无    1-充满    2-放空"
usStackHoldTemp[49]	心跳	1-255	
*/
void TcpModbDev::writeSlaveData()// 从机写入数据给主机
{
    int pos = 0;
    int iLenVal = 0;
    quint16 dataBuf[50];
    memset(dataBuf, 0,sizeof(dataBuf));

    /*
	*/

    //quint16 usStackHoldTemp[50];             // 30 - 79
    dataBuf[pos++] = getUint16(KgGlobalData::ms_pStack->fStackVol);  // usStackHoldTemp[35]
    dataBuf[pos++] = getUint16(KgGlobalData::ms_pStack->fStackCur);
    dataBuf[pos++] = getUint16(KgGlobalData::ms_pStack->fStackSoc*10);
    dataBuf[pos++] = getUint16(KgGlobalData::ms_pStack->fStackSoh*10);
    dataBuf[pos++] = getUint16(KgGlobalData::ms_pStack->fBankMaxChargeCurrent);    // usStackHoldTemp[39]
    dataBuf[pos++] = getUint16(KgGlobalData::ms_pStack->fBankMaxDischargeCurrent); // usStackHoldTemp[40]
    dataBuf[pos++] = getUint16(KgGlobalData::ms_pStack->fBankMaxChargePower);      // usStackHoldTemp[41]
    dataBuf[pos++] = getUint16(KgGlobalData::ms_pStack->fBankMaxDischargePower);   // usStackHoldTemp[42]
    dataBuf[pos++] = KgGlobalData::ms_pStack->usStackState; // usStackHoldTemp[43]  BMS总状态
    dataBuf[pos++] = 0;// getContactorState();// usStackHoldTemp[44] 主接触器状态	1-闭合 2-断开
    dataBuf[pos++] = 0;// getAlarmWord(1);// usStackHoldTemp[45] 轻度告警字
    dataBuf[pos++] = 0;// getAlarmWord(2);// usStackHoldTemp[46] 中度告警字
    dataBuf[pos++] = 0;// getAlarmWord(3);// usStackHoldTemp[47] 严重告警字

    // BMS状态字 Bit0:1-BMS与EMS通信故障 0-BMS与EMS通信正常              // usStackHoldTemp[48]
    //           Bit2-Bi3:0-无    1-充满    2-放空
    dataBuf[pos++] = 0;// getBmsState();// BMS状态字

    dataBuf[pos++] = g_heartbeat;// 心跳     // usStackHoldTemp[49]
    if(++g_heartbeat > 255)
    {
        g_heartbeat = 1;
    }

    uchar uaAddr = 1;
    m_uaFuncCode = 0x10;
    m_usRegAddr = 65;
    quint16 regCount = pos;
    iLenVal =  m_pModbusFactory->formSetMultgram(50, uaAddr, m_usRegAddr, regCount, dataBuf, m_pSendBuf);
    if (0 == sendRecvData(m_pSendBuf,regCount,iLenVal))
    {
        if(g_testLogSecCount < 100)
        {
            g_testLogSecCount += 1;
            writeKgLogfile(QString("============writeSlaveData  OK (devAddr:1)."));
        }
    }
    else
    {
        writeKgLogfile(QString("============writeSlaveData  failed (devAddr:1)."));
    }
}

/*
新疆盛全主机BA			
usStackHoldTemp[0]		从机BA数据写入标志	1-从机BA数据写入标志                0-没有写入
usStackHoldTemp[1]		从机BA电池最高温度	放大10倍
usStackHoldTemp[2]		从机BA电池最低温度	放大10倍
usStackHoldTemp[3]		从机BA电池平均温度	放大10倍
*/
void TcpModbDev::writeMinMaxTempData() // added 2023-11-28
{
    int iLenVal = 0;
    int iInedx = 0;
    QString str;

    if(g_testLogCount < 100)
    {
        g_testLogCount += 1;
        writeKgLogfile( QString("writeMinMaxTempData"));
    }

    float fMaxSglTemp = 0;// getMaxSglTemp();
    float fMinSglTemp = 0;// getMinSglTemp();
    float fAvgSglTemp = 0;// getAvgSglTemp();

    quint16 dataBuf[10] = {0,0,0,0,0};
    if(fMaxSglTemp == fMinSglTemp) // 温度数据无效
    {
        dataBuf[0] = 0;// 标记无效
    }
    else
    {
        dataBuf[0] = 1;// 标记有效
    }
    dataBuf[1] = getUint16(fMaxSglTemp * 10);
    dataBuf[2] = getUint16(fMinSglTemp * 10);
    dataBuf[3] = getUint16(fAvgSglTemp * 10);

    uchar uaAddr = 1;
    m_uaFuncCode = 0x10;
    m_usRegAddr = 30;
    quint16 regCount = 4;
    // Send:00 32 00 00 00 0F 01 10 00 1E 00 04 08 | 00 01 01 5E 00 E1 01 00
    // Recv:00 32 00 00 00 06 01 10 00 1E 00 04
    //printf("===================1\n");
    iLenVal =  m_pModbusFactory->formSetMultgram(50, uaAddr, m_usRegAddr, regCount, dataBuf, m_pSendBuf);
    //printf("===================2\n");
    if (0 == sendRecvData(m_pSendBuf,regCount,iLenVal))
    {
        if(g_testLogCount < 100)
        {
            g_testLogCount += 1;
            writeKgLogfile(QString("============writeMinMaxTempData  OK (devAddr:1)."));
        }
    }
    else
    {
        writeKgLogfile(QString("============writeMinMaxTempData  failed (devAddr:1)."));
    }
}


void InitDevData()
{
    BrotherBaData &devData = g_brotherBaData;//KgGlobalData::ms_brotherBaData;
    //devData.xfSpray = 0;
    memset(&devData, 0,  sizeof(BrotherBaData));
    devData.bReaded = false;
    devData.failedCount = 1000;  //接收数据失败次数
    devData.devAddr = 1;
}

void TcpModbDev::JudgeDevConnError(BrotherBaData &dev)
{
    // 这里只输出日志，不参与策略 2021-1-7
    if(dev.failedCount >= 15)
    {
        if(0 == dev.connError || 99 == dev.connError) // modified 2023-2-17
        {
            //QString strLog = QString("设备(%1,%2)通迅故障.").arg(m_strIP).arg(m_usPort);
            //saveLogToBaDb(strLog);
        }
        dev.connError = 1;
    }
    else if (dev.failedCount < 1)
    {
        if(1 == dev.connError)
        {
            //QString strLog = QString("设备(%1,%2)通迅恢复.").arg(m_strIP).arg(m_usPort);
            //saveLogToBaDb(strLog);
        }
        dev.connError = 0;
    }
    else
    {
        writeKgLogfile(QString("===============failedCount:%1 connError:%2.")
                           .arg(dev.failedCount).arg((int)dev.connError));
    }
}

int g_readDevCount = 0;//程序刚运行时计数
void TcpModbDev::run()
{
    char *pData;
    int i;
    int k;
    int iIndexStep = 50;
    int iRetVal = -1;
    m_iErrNum = 0;
    unsigned int runingTime = 0;//记录运行时间

    int failedCount = 0;
    m_pTcpClient = new QTcpSocket;//(this);
    QObject::connect(m_pTcpClient, SIGNAL(disconnected()), this, SLOT(disconnected()));
    sleep(1);
    printf("********TcpModbDev::run()\n");

    InitDevData();

    CBattStack *pStack = KgGlobalData::ms_pRTDB->getStack(0);
    if (NULL == pStack)
    {
        //continue;
    }

    //pStack->fStackTemp[0] = 13;    // testing
    //pStack->fStackTemp[1] = 16;
    //pStack->usStackTemp[28] = 280;// testing
    //pStack->usStackTemp[29] = 290;
    int m_connFailedCount = 0;

    while(1)
    {
        msleep(100);
        if (runingTime < 180 * 1000)//最多记录180秒
            runingTime += 30;

        if (!m_bTcpConnected)
        {
            //if (NULL != m_pTcpClient)
            //	m_pTcpClient->deleteLater();
            // connect to server
            emit addLog(RUN_LOG_MESSAGE_PCS, QString("Try to connnect USR(%1:%2)...").arg(m_strIP).arg(m_usPort));
            m_pTcpClient->connectToHost(m_strIP, m_usPort);
            if (!m_pTcpClient->waitForConnected(2000))
            {
                ++failedCount;
                emit addLog(RUN_LOG_FAILED_PCS, QString("Try to connnect USR(%1:%2) FAILED.(Err Code:%4 Err Info:%5").arg(m_strIP).arg(m_usPort).arg(m_pTcpClient->error()).arg(m_pTcpClient->errorString()));
                //++m_connFailedCount;
                //if(m_connFailedCount >= 5)
                //{
                m_connFailedCount = 0;
                if(0 == m_connErrorLog || 99 == m_connErrorLog) // modified 2023-2-17
                {
                    if(KgGlobalData::ms_devNo >= 2)// modified 2023-12-30
                    {
                        QString strLog = kgConvert("连接主机(%1,%2)失败.").arg(m_strIP).arg(m_usPort);
                        QString strContextEn = QString("connect master(%1:%2) failed").arg(m_strIP).arg(m_usPort);
                        saveLogToBaDb(strLog, strContextEn);
                    }
                    else
                    {
                        QString strLog = kgConvert("连接从机(%1,%2)失败.").arg(m_strIP).arg(m_usPort);
                        QString strContextEn = QString("connect slave(%1:%2) failed").arg(m_strIP).arg(m_usPort);
                        saveLogToBaDb(strLog, strContextEn);
                    }

                    QString strLog = QString("********connnect failed.");
                    writeKgLogfile(strLog);
                }
                m_connErrorLog = 1;
                //}



                BrotherBaData &dev = g_brotherBaData;//KgGlobalData::ms_brotherBaData;
                //tmpHumd.connError = 1;// modified 2023-2-17 原来是1-故障，则保持
                // TCP连接断开时，TEMPHD通信故障没有报，则恢复时也不要报恢复，所以要改为99
                if(0 == dev.connError)
                    dev.connError = 99;

                dev.failedCount = 1000;
                //strLog = QString("====BrotherBaData connError=%1.").arg(dev.connError);
                //writeKgLogfile(strLog);

                //msleep(3*1000);
                continue;
            }
            else
            {
                failedCount = 0;
                m_connFailedCount = 0;
                emit addLog(RUN_LOG_MESSAGE_PCS, QString("Connnect to BA(%1:%2) OK.").arg(m_strIP).arg(m_usPort));
                writeKgLogfile(QString("Connnect to BA  OK."));
                m_bTcpConnected = true;

                //pPcsInfo->onlineState = 1;//在线
                if(1 == m_connErrorLog) // modified 2023-2-17
                //if(1 == m_connErrorLog || 99 == m_connErrorLog)
                {
                    //QString strLog = QString("连接USR-580(地址:%1,端口:%2)成功.").arg(m_strIP).arg(m_usPort);
                    if(KgGlobalData::ms_devNo >= 2)// modified 2023-12-30
                    {
                        QString strLog = kgConvert("连接主机(%1,%2)成功.").arg(m_strIP).arg(m_usPort);
                        QString strContextEn = QString("connect master(%1:%2) ok").arg(m_strIP).arg(m_usPort);
                        saveLogToBaDb(strLog, strContextEn);
                    }
                    else
                    {
                        QString strLog = kgConvert("连接从机(%1,%2)成功.").arg(m_strIP).arg(m_usPort);
                        QString strContextEn = QString("connect slave(%1:%2) ok").arg(m_strIP).arg(m_usPort);
                        saveLogToBaDb(strLog, strContextEn);
                    }
                }
                m_connErrorLog = 0;
            }
        }
        else
        {
            if(KgGlobalData::ms_devNo >= 2)// modified 2023-12-30
            {
                //writeMinMaxTempData();// 从机BA电池最高最低温度 写入主机 (新疆盛全)
                KgReadDevData(g_brotherBaData);
            }

            if(KgGlobalData::ms_devNo >= 2)// modified 2023-12-30
            {
                //writeSlaveData();// 从机写入数据给主机,供主机汇总 (楚能华锐)
            }

            JudgeDevConnError(g_brotherBaData);// KgGlobalData::ms_brotherBaData

            //writeKgLogfile("=======================end");

            if (g_readDevCount < 100)
                g_readDevCount += 1;
        }

        if (m_iErrNum >= 7)// modified 2023-4-19
        {
            writeKgLogfile(QString("******** m_pTcpClient->close()"));

            m_pTcpClient->close();
            m_bTcpConnected = false;
            m_iErrNum = 0;
            emit addLog(RUN_LOG_FAILED_PCS, QString("Dev(%1:%2) Disconnected FORCIBLY.").arg(m_strIP).arg(m_usPort));
        }

        //延时0.5秒
        for(i = 0; i < 5; ++i)
        {
            msleep(100);
        }
    }
}

void TcpModbDev::readReplyHead(char* pDataBuf, SMdobusTcpReply &reply, int &iInedx)
{
    m_pModbusFactory->getParamFromBuffer(pDataBuf, reply.usEvent);
    iInedx += 2;

    m_pModbusFactory->getParamFromBuffer(pDataBuf + iInedx, reply.usProto);
    iInedx += 2;

    m_pModbusFactory->getParamFromBuffer(pDataBuf + iInedx, reply.usLen);
    iInedx += 2;

    reply.uaAddr = (uchar)*(pDataBuf + iInedx);
    iInedx += 1;

    reply.uaFuncCode = (uchar)*(pDataBuf + iInedx);
    iInedx += 1;

    reply.usDataLen = (uchar)*(pDataBuf + iInedx);
    iInedx += 1;
}

int g_readCount = 0;
int g_printDhCount = 0;
void TcpModbDev::readDevData1(char* pDataBuf, int iRetVal, BrotherBaData &dev)
{
    int iInedx = 0;

    SMdobusTcpReply reply;
    readReplyHead(pDataBuf,reply,iInedx);
    CBattStack *pStack = KgGlobalData::ms_pStack;
    CBAComReg *pBAComReg = KgGlobalData::ms_pRTDB->getBAComReg(0);


    if(g_printDhCount < 50)
    {
        g_printDhCount += 1;
    }

    quint16 uiParamVal = 0;
    m_pModbusFactory->getParamFromBuffer(pDataBuf + iInedx, uiParamVal); //
    iInedx += 2;
    //dev.aZlThunder = uiParamVal;
    quint16 xfAlarmWord = uiParamVal;
    dev.xfState = uiParamVal;

    m_pModbusFactory->getParamFromBuffer(pDataBuf + iInedx, uiParamVal); //
    iInedx += 2;
    //dev.aJlThunder = uiParamVal;
    quint16 otherWord = uiParamVal;
    dev.otherState = uiParamVal;

    quint16 xfAlarm = ((xfAlarmWord & 1) > 0) ? 1: 0;
    quint16 xfSprayAlarm = ((xfAlarmWord & 2) > 0) ? 1: 0;
    quint16 xfFaultAlarm = ((xfAlarmWord & 4) > 0) ? 1: 0;
    quint16 xfManuAuto = ((xfAlarmWord & 8) > 0) ? 1: 0;

    if(1 != pStack->aFireAction && 1 == xfSprayAlarm) // added 2024-1-6
    {
        saveLogToBaDb("主机发生消防二级告警.", "fire level2 alarm starting.");
    }

    if(1 == pStack->aFireAction && 1 != xfSprayAlarm)
    {
        saveLogToBaDb("主机消防二级告警结束.", "fire level2 alarm finished.");
    }

    if(1 == xfSprayAlarm)
    {
        pStack->aFireAction = 1;
    }
    else
    {
        pStack->aFireAction = 0;
    }



    if(g_printDhCount < 50)
    {
        g_printDhCount += 1;
    }



}


BrotherBaData g_brotherBaData;
QString g_brotherBaIp;  //  另一台BA的IP
int g_brotherBaPort = 0;    //  另一台BA的端口
